﻿using MediumApi.Db;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static MediumApi.Param.AppParam;
using static MediumApi.Result.AppResult;

namespace MediumApi.Service
{
    public class PermissionService : ITransientService
    {
        private readonly AppDbContext _context;
        public PermissionService(AppDbContext context)
        {
            _context = context;
        }

        //菜单
        public async Task<int> AddMenu(AddMenuParam param)
        {
            Menu menu = new Menu()
            {
                ManagerId = param.ManagerId,
                MenuName = param.MenuName,
                MenuPath = param.MenuPath,
                Sort = param.Sort,
                Status = param.Status,
                icon = param.icon,
                MenuType = param.MenuType,
                PageTableId = param.PageTableId,
                CreatedAt = DateTime.Now,
            };
            await _context.menus.AddRangeAsync(menu);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> UpdateMenu(AddMenuParam param)
        {
            var data = await _context.menus.FirstOrDefaultAsync(e => e.Id == param.Id);
            if (data != null)
            {
                data.ManagerId = param.ManagerId;
                if (!string.IsNullOrEmpty(param.MenuName))
                {
                    data.MenuName = param.MenuName;
                }
                if (!string.IsNullOrEmpty(param.MenuPath))
                {
                    data.MenuPath = param.MenuPath;
                }
                data.PageTableId = param.PageTableId;
                if (!string.IsNullOrEmpty(param.icon))
                {
                    data.icon = param.icon;
                }
                data.MenuType = param.MenuType;
                data.Sort = param.Sort;
                data.Status = param.Status;
            }
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> DelMenu(int Id)
        {
            var data = await _context.menus.FirstOrDefaultAsync(e => e.Id == Id);
            if (data == null) return 0;
            _context.menus.Remove(data);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        // 获取所有菜单（带层级结构）
        public async Task<List<SelectMenuListResult>> GetAllMenusAsync(int RoleId = 0)
        {
            var flatMenus = await _context.menus.ToListAsync();
            List<RoleMenu> RoleMenu = new List<RoleMenu>();
            RoleMenu = await _context.roleMenus.Where(r => r.RoleId == RoleId && r.halfCheckedKeys == 2).ToListAsync();
            return BuildMenuTree(RoleMenu, flatMenus, RoleId);
        }
        // 构建菜单树
        private List<SelectMenuListResult> BuildMenuTree(List<RoleMenu> rolemenu, List<Menu> flatMenus, int RoleId, int? parentId = 0)
        {
            List<SelectMenuListResult> menuList = new List<SelectMenuListResult>();
            if (RoleId == 1)
            {
                menuList = flatMenus
                    .Where(m => m.ManagerId == parentId)
                    .OrderBy(m => m.Sort)
                    .Select(m => new SelectMenuListResult
                    {
                        Id = m.Id,
                        ManagerId = m.ManagerId,
                        MenuName = m.MenuName,
                        MenuPath = m.MenuPath,
                        PageTableId = m.PageTableId,
                        icon = m.icon,
                        MenuType = m.MenuType,
                        Sort = m.Sort,
                        Status = m.Status,
                        MenuResults = BuildMenuTree(rolemenu, flatMenus, RoleId, m.Id)
                    })
                    .ToList();
            }
            else
            {
                menuList = rolemenu.Where(r => r.RoleId == RoleId).Join(
            flatMenus.Where(a => a.ManagerId == parentId),
            r => r.MenuId,
            p => p.Id,
            (r, p) => new SelectMenuListResult
            {
                Id = p.Id,
                ManagerId = p.ManagerId,
                MenuName = p.MenuName,
                MenuPath = p.MenuPath,
                PageTableId = p.PageTableId,
                icon = p.icon,
                MenuType = p.MenuType,
                Sort = p.Sort,
                Status = p.Status,
                MenuResults = BuildMenuTree(rolemenu, flatMenus, RoleId, p.Id)
            }).OrderBy(c => c.Sort).ToList();
            }
            return menuList;
        }

        public async Task<List<SelectMenuListResult>> GetRoleMenusAsync(int RoleId = 0)
        {
            var flatMenus = await _context.menus.ToListAsync();
            var RoleMenu = await _context.roleMenus.Where(r => r.RoleId == RoleId && r.halfCheckedKeys == 2).ToListAsync();
            return RoleBuildMenu(RoleMenu, flatMenus, RoleId);
        }
        // 构建菜单树
        private List<SelectMenuListResult> RoleBuildMenu(List<RoleMenu> rolemenu, List<Menu> flatMenus, int RoleId, int? parentId = 0)
        {
            List<SelectMenuListResult> menuList = new List<SelectMenuListResult>();
            if (RoleId == 1)
            {
                menuList = flatMenus
                    .Where(m => m.ManagerId == parentId && m.MenuType != 3)
                    .OrderBy(m => m.Sort)
                    .Select(m => new SelectMenuListResult
                    {
                        Id = m.Id,
                        ManagerId = m.ManagerId,
                        MenuName = m.MenuName,
                        MenuPath = m.MenuPath,
                        PageTableId = m.PageTableId,
                        icon = m.icon,
                        MenuType = m.MenuType,
                        Sort = m.Sort,
                        Status = m.Status,
                        MenuResults = RoleBuildMenu(rolemenu, flatMenus, RoleId, m.Id)
                    })
                    .ToList();
            }
            else
            {
                menuList = rolemenu.Where(r => r.RoleId == RoleId).Join(
                flatMenus.Where(a => a.ManagerId == parentId && a.MenuType != 3),
                r => r.MenuId,
                p => p.Id,
                (r, p) => new SelectMenuListResult
                {
                    Id = p.Id,
                    ManagerId = p.ManagerId,
                    MenuName = p.MenuName,
                    MenuPath = p.MenuPath,
                    PageTableId = p.PageTableId,
                    icon = p.icon,
                    MenuType = p.MenuType,
                    Sort = p.Sort,
                    Status = p.Status,
                    MenuResults = RoleBuildMenu(rolemenu, flatMenus, RoleId, p.Id)
                }).OrderBy(c => c.Sort).ToList();
            }
            //}
            return menuList;
        }

        public async Task<List<SelectMenuListResult>> btnGetAllMenusAsync(int RoleId = 0)
        {
            var flatMenus = await _context.menus.Where(m => m.MenuType == 3).ToListAsync();
            var RoleMenu = await _context.roleMenus.Where(r => r.RoleId == RoleId && r.halfCheckedKeys == 2).ToListAsync();
            return BtnBuildMenuTree(RoleMenu, flatMenus, RoleId);
        }
        private List<SelectMenuListResult> BtnBuildMenuTree(List<RoleMenu> rolemenu, List<Menu> flatMenus, int RoleId, int? parentId = 0)
        {
            List<SelectMenuListResult> menuList = new List<SelectMenuListResult>();
            if (RoleId == 1)
            {
                menuList = flatMenus
                    .Where(m => m.MenuType == 3)
                    .OrderBy(m => m.Sort)
                    .Select(m => new SelectMenuListResult
                    {
                        Id = m.Id,
                        ManagerId = m.ManagerId,
                        MenuName = m.MenuName,
                        MenuPath = m.MenuPath,
                        PageTableId = m.PageTableId,
                        icon = m.icon,
                        MenuType = m.MenuType,
                        Sort = m.Sort,
                        Status = m.Status,
                        MenuResults = new List<SelectMenuListResult>()
                    })
                    .ToList();
            }
            else
            {
                menuList = rolemenu.Where(r => r.RoleId == RoleId).Join(
                flatMenus,
                r => r.MenuId,
                p => p.Id,
                (r, p) => new SelectMenuListResult
                {
                    Id = p.Id,
                    ManagerId = p.ManagerId,
                    MenuName = p.MenuName,
                    MenuPath = p.MenuPath,
                    PageTableId = p.PageTableId,
                    icon = p.icon,
                    MenuType = p.MenuType,
                    Sort = p.Sort,
                    Status = p.Status,
                }).OrderBy(c => c.Sort).ToList();
            }
            return menuList;
        }
        // 获取某个菜单的所有子菜单（无限级）
        public async Task<List<Menu>> GetDescendantMenusAsync(int menuId)
        {
            var allMenus = await _context.menus.ToListAsync();
            var result = new List<Menu>();
            GetDescendants(allMenus, menuId, result);
            return result;
        }
        private void GetDescendants(List<Menu> allMenus, int parentId, List<Menu> result)
        {
            var children = allMenus.Where(m => m.ManagerId == parentId).ToList();
            foreach (var child in children)
            {
                result.Add(child);
                GetDescendants(allMenus, child.Id, result);
            }
        }





        //角色菜单
        public async Task<int> AddRolePageTable(AddRoleMenuParam param)
        {
            var roleMenus1 = await _context.roleMenus.Where(e => e.RoleId == param.RoleId).ToListAsync();
            List<RoleMenu> roleMenus2 = new List<RoleMenu>();



            foreach (var item in param.MenuId)
            {
                var roleMenus = await _context.roleMenus.FirstOrDefaultAsync(e => e.MenuId == item && e.RoleId == param.RoleId && e.halfCheckedKeys == 2);
                if (roleMenus == null)
                {
                    RoleMenu roleMenu = new RoleMenu()
                    {
                        RoleId = param.RoleId,
                        MenuId = item,
                        halfCheckedKeys = 2
                    };
                    await _context.roleMenus.AddRangeAsync(roleMenu);
                }
                else
                {
                    roleMenus2.Add(roleMenus);
                }
            }
            foreach (var item in param.halfCheckedKeys)
            {
                var roleMenus = await _context.roleMenus.FirstOrDefaultAsync(e => e.MenuId == item && e.RoleId == param.RoleId && e.halfCheckedKeys == 1);
                if (roleMenus == null)
                {
                    RoleMenu roleMenu = new RoleMenu()
                    {
                        RoleId = param.RoleId,
                        MenuId = item,
                        halfCheckedKeys = 1
                    };
                    await _context.roleMenus.AddRangeAsync(roleMenu);
                }
                else
                {
                    roleMenus2.Add(roleMenus);
                }
            }

            var differences1 = roleMenus1.Except(roleMenus2).ToList();
            _context.roleMenus.RemoveRange(differences1);

            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> DelRolePageTable(int RoleMenuId)
        {
            var data = await _context.roleMenus.FirstOrDefaultAsync(e => e.Id == RoleMenuId);
            if (data == null) return 0;
            _context.roleMenus.Remove(data);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<SelectRoleMenuListResult> SelectRolePageTableList(SelectRolePageTableListParam param)
        {

            SelectRoleMenuListResult selectRoleMenuListResult = new SelectRoleMenuListResult()
            {
                RoleId = param.RoleId,
                MenuId = await _context.roleMenus.Where(r => r.RoleId == param.RoleId && r.halfCheckedKeys == 2).Select(a => a.MenuId).ToListAsync(),
                halfCheckedKeys = await _context.roleMenus.Where(r => r.RoleId == param.RoleId && r.halfCheckedKeys == 1).Select(a => a.MenuId).ToListAsync(),
            };

            //var data = await _context.roleMenus.Where(r => r.RoleId == param.RoleId).Select(c => new SelectRoleMenuListResult
            //{
            //    Id = c.Id,
            //    RoleId = c.RoleId,
            //    MenuId = c.MenuId,
            //    halfCheckedKeys = c.halfCheckedKeys
            //}).OrderBy(c => c.Id).ToListAsync();
            return selectRoleMenuListResult;
        }

        //页面
        public async Task<int> AddPageTable(AddPageTableParam param)
        {
            PageTable role = new PageTable()
            {
                PageName = param.PageName,
                PageGrade = param.PageGrade,
                PagePath = param.PagePath,
                ManagerId = param.ManagerId,
                CreatedAt = DateTime.Now,
            };
            await _context.pageTables.AddRangeAsync(role);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> UpdatePageTable(AddPageTableParam param)
        {
            var data = await _context.pageTables.FirstOrDefaultAsync(e => e.Id == param.Id);
            if (data != null)
            {
                if (!string.IsNullOrEmpty(param.PageName))
                {
                    data.PageName = param.PageName;
                }
                if (!string.IsNullOrEmpty(param.PagePath))
                {
                    data.PagePath = param.PagePath;
                }
                data.PageGrade = param.PageGrade;
            }
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> DelPageTable(int Id)
        {
            var data = await _context.pageTables.FirstOrDefaultAsync(e => e.Id == Id);
            if (data == null) return 0;
            _context.pageTables.Remove(data);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<List<SelectPageTableListResult>> SelectPageTableList()
        {
            var data = await _context.pageTables.Select(c => new SelectPageTableListResult
            {
                Id = c.Id,
                PageName = c.PageName,
                PageGrade = c.PageGrade,
                PagePath = c.PagePath,
                CreatedAt = c.CreatedAt,
            }).OrderByDescending(c => c.CreatedAt).ToListAsync();
            return data;
        }


        //角色
        public async Task<int> AddRole(AddRoleParam param)
        {
            Role role = new Role()
            {
                RoleName = param.RoleName,
                CreatedAt = DateTime.Now,
                Status = param.Status,
                Describe = param.Describe,
            };
            await _context.roles.AddRangeAsync(role);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> UpdateRole(AddRoleParam param)
        {
            var data = await _context.roles.FirstOrDefaultAsync(e => e.Id == param.Id);
            if (data != null)
            {
                if (!string.IsNullOrEmpty(param.RoleName))
                {
                    data.RoleName = param.RoleName;
                }
                if (!string.IsNullOrEmpty(param.Describe))
                {
                    data.Describe = param.Describe;
                }
                data.Status = param.Status;
            }
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<int> DelRole(int Id)
        {
            var data = await _context.roles.FirstOrDefaultAsync(e => e.Id == Id);
            if (data == null) return 0;
            _context.roles.Remove(data);
            int affectedRows = await _context.SaveChangesAsync();
            return affectedRows;
        }
        public async Task<List<SelectRoleListResult>> SelectRoleList()
        {
            var data = await _context.roles.Select(c => new SelectRoleListResult
            {
                Id = c.Id,
                RoleName = c.RoleName,
                CreatedAt = c.CreatedAt,
                Status = c.Status,
                Describe = c.Describe,
            }).OrderByDescending(c => c.CreatedAt).ToListAsync();
            return data;
        }
    }
}
